import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

/**
 * Smith Chart display window for S22 (2N3478 example)
 * Can be instantiated directly: new SmithChartPlotter22()
 */
public class SmithChartPlotter22 extends JFrame {

    // S22 measurement data: [frequency Hz, Re(Γ), Im(Γ)]
    private static final double[][] POINTS = {
        {100000000,  0.800000000000,  0.000000000000},
        {300000000,  0.856777782589, -0.099882061573},
        {500000000,  0.844951415062, -0.143665313721},
        {900000000,  0.810318946838, -0.231232166290},
        {1300000000, 0.746723175049, -0.365879058838},
        {1700000000, 0.561097256858, -0.778054862843}
    };

    /**
     * Constructor creates and shows the complete chart window
     */
    public SmithChartPlotter22() {
        super("Smith Chart - 2N3478 S22");
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);  // only close this window

        // Create and add the drawing panel
        SmithChartPanel chartPanel = new SmithChartPanel();
        add(chartPanel);

        // Reasonable size + center
        setSize(760, 820);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    /**
     * Inner class: the actual drawing component (this is the JPanel)
     */
    private static class SmithChartPanel extends JPanel {

        public SmithChartPanel() {
            setBackground(Color.WHITE);
            setPreferredSize(new Dimension(700, 750));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;

            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            int w = getWidth();
            int h = getHeight();
            int cx = w / 2;
            int cy = h / 2;
            int radius = Math.min(w, h) / 2 - 60;

            // Outer circle
            g2.setColor(Color.BLACK);
            g2.setStroke(new BasicStroke(2.2f));
            g2.draw(new Ellipse2D.Double(cx - radius, cy - radius, 2 * radius, 2 * radius));

            // Real axis
            g2.draw(new Line2D.Double(cx - radius, cy, cx + radius, cy));

            // Some resistance circles
            double[] resistances = {0.2, 0.5, 1.0, 2.0, 5.0};
            for (double r : resistances) {
                drawResistanceCircle(g2, cx, cy, radius, r);
            }

            // Plot the points
            g2.setColor(new Color(200, 0, 60));  // nice red
            g2.setStroke(new BasicStroke(3.0f));

            Point2D prev = null;
            for (double[] p : POINTS) {
                Point2D pt = gammaToPixel(p[1], p[2], cx, cy, radius);

                g2.fill(new Ellipse2D.Double(pt.getX() - 7, pt.getY() - 7, 14, 14));

                long freqMHz = Math.round(p[0] / 1_000_000);
                g2.setColor(Color.BLACK);
                g2.setFont(new Font("Segoe UI", Font.PLAIN, 13));
                g2.drawString(freqMHz + " MHz", (float)pt.getX() + 14, (float)pt.getY() - 10);

                if (prev != null) {
                    g2.setColor(new Color(200, 0, 60));
                    g2.draw(new Line2D.Double(prev, pt));
                }
                prev = pt;
            }

            // Title
            g2.setColor(Color.BLACK);
            g2.setFont(new Font("Segoe UI", Font.BOLD, 22));
            g2.drawString("Smith Chart - 2N3478 S22", cx - 190, 55);
        }

        private Point2D gammaToPixel(double re, double im, int cx, int cy, int radius) {
            return new Point2D.Double(cx + re * radius, cy - im * radius);
        }

        private void drawResistanceCircle(Graphics2D g2, int cx, int cy, int radius, double r) {
            if (r <= 0) return;
            double x = cx + radius * (r / (r + 1.0));
            double rad = radius * (1.0 / (r + 1.0));
            g2.setColor(new Color(100, 100, 100, 180));
            g2.setStroke(new BasicStroke(1.0f));
            g2.draw(new Ellipse2D.Double(x - rad, cy - rad, 2 * rad, 2 * rad));
        }
    }
}